﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Live;
using SMSAssistant.Resources;
using SMSAssistant.ViewModels;
using Microsoft.Phone.Shell;
using System.Runtime.Serialization.Json;
using System.IO;
using SMSAssistant.Model;
using Coding4Fun.Phone.Controls;

namespace SMSAssistant
{
    public partial class BackUpView : PhoneApplicationPage
    {
        static LiveConnectClient client;
        static LiveConnectSession session;
        static LiveConnectSessionStatus status;
        System.IO.MemoryStream stream;
        const string skyDriveFolderName = "smsassistantbackup";
        string skyDriveFolderID;
        BackupViewModel viewmodel;
        int count;
        public BackUpView()
        {
            InitializeComponent();

            InitLabel();

            Loaded += new RoutedEventHandler(BackUpView_Loaded);
        }

        void BackUpView_Loaded(object sender, RoutedEventArgs e)
        {
            DataContext = viewmodel = new BackupViewModel();
            //throw new NotImplementedException();
            BuildApplicationBar();
        }

        private void InitLabel()
        {
            PageTitle.Text = Resource.BackupListHeader;
            signinBtn.SignInText = Resource.SigninText;
            signinBtn.SignOutText = Resource.SignoutText;
            //throw new NotImplementedException();
        }

        private void SignInButton_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
                return;
            }

            status = e.Status;
            session = e.Session;

            if (e.Session != null &&
        e.Status == LiveConnectSessionStatus.Connected)
            {
                InitClient(e.Session);
                client.GetAsync("me", null);
                SetBusy(true,Resource.LoadingProfile);
            }
            else
            {
                userName.Text = string.Empty;
                client = null;
                ApplicationBar.IsVisible = false;
            }
        }

        private void InitClient(Microsoft.Live.LiveConnectSession session)
        {
            client = new LiveConnectClient(session);
            //infoTextBlock.Text = "Signed in.";
            client.GetCompleted +=
                new EventHandler<LiveOperationCompletedEventArgs>(btnSignin_GetCompleted);
            client.UploadCompleted += new EventHandler<LiveOperationCompletedEventArgs>(ISFile_UploadCompleted);
            client.PostCompleted += new EventHandler<LiveOperationCompletedEventArgs>(CreateFolder_Completed);
            client.DeleteCompleted += new EventHandler<LiveOperationCompletedEventArgs>(client_DeleteCompleted);
        }

        void client_DeleteCompleted(object sender, LiveOperationCompletedEventArgs e)
        {
            SetBusy(false);
            //throw new NotImplementedException();
            var backup = e.UserState as Backup;
            if (e.Error == null)
            {
                if (backup != null)
                {
                    viewmodel.Delete(backup);
                }
            }
            else
            {
                //infoTextBlock.Text = "Error calling API: " + 
                if (e.Error.Message.Contains(Resource.DoesNotExist))
                {
                    if (backup != null)
                    {
                        viewmodel.Delete(backup);
                    }
                }
                else
                    MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }

        void btnSignin_GetCompleted(object sender, LiveOperationCompletedEventArgs e)
        {
            SetBusy(false);
            client.GetCompleted -= btnSignin_GetCompleted;
            if (e.Error == null)
            {
                //infoTextBlock.Text = "Hello, signed-in user!"; 
                //
                if (e.Result.ContainsKey("name"))
                {
                    userName.Text = "Hi," + e.Result["name"].ToString();
                }
                ApplicationBar.IsVisible = true;
            }
            else
            {
                //infoTextBlock.Text = "Error calling API: " + 

                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }

        private void BuildApplicationBar()
        {
            // Set the page's ApplicationBar to a new instance of ApplicationBar.
            ApplicationBar = new ApplicationBar() { Opacity = .5 };

            // Create a new button and set the text value to the localized string from AppResources.
            ApplicationBarIconButton addBackupButton = new ApplicationBarIconButton(new Uri("/Images/AppBarIcons/appbar.add.rest.png", UriKind.Relative));
            addBackupButton.Click += new EventHandler(addBackupButton_Click);
            addBackupButton.Text = Resource.CreateNewBackup;
            ApplicationBar.Buttons.Add(addBackupButton);

            ApplicationBarIconButton deleteBackupButton = new ApplicationBarIconButton(new Uri("/Images/AppBarIcons/delete.png", UriKind.Relative));
            deleteBackupButton.Click += new EventHandler(deleteBackupButton_Click); ;
            deleteBackupButton.Text = Resource.Delete;
            ApplicationBar.Buttons.Add(deleteBackupButton);

            ApplicationBarIconButton syncBackupButton = new ApplicationBarIconButton(new Uri("/Images/AppBarIcons/refresh.png", UriKind.Relative));
            syncBackupButton.Click += new EventHandler(syncBackupButton_Click); ;
            syncBackupButton.Text = Resource.Delete;
            ApplicationBar.Buttons.Add(syncBackupButton);

            ApplicationBar.IsVisible = false;
            //// Create a new menu item with the localized string from AppResources.
            //ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(Resource.PinToStart);
            //appBarMenuItem.Click += ApplicationBarMenuItem_Click;
            //ApplicationBar.MenuItems.Add(appBarMenuItem);

            //// Create a new menu item with the localized string from AppResources.
            //ApplicationBarMenuItem appBarMenuItem2 = new ApplicationBarMenuItem(Resource.BackupMenuItemLabel);
            //appBarMenuItem2.Click += ApplicationBarMenuItem2_Click;
            //ApplicationBar.MenuItems.Add(appBarMenuItem2);
        }

        void addBackupButton_Click(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            if (session == null || status != LiveConnectSessionStatus.Connected)
            {
                MessageBox.Show(Resource.SigninRequired,"", MessageBoxButton.OK);
            }
            else
            {
                count = viewmodel.MsgDB.Messages.Count();
                if (count == 0)
                {
                    MessageBox.Show("No message to backup");
                    return;
                }

                if (string.IsNullOrEmpty(skyDriveFolderID))
                {
                    client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(GetFolderProperties_Completed);
                    // If you put photo to folder it becomes album. 
                    client.GetAsync("me/skydrive/files?filter=folders");
                }
                else
                    UploadFile();

                SetBusy(true,Resource.CreatingBackup);
            }
        }

        private void SetBusy(bool isBusy,string msg=" ")
        {
            progressIndicator.IsIndeterminate = isBusy;
            ApplicationBar.IsVisible = !isBusy;
            msgLabel.Text = msg;
        }

        private void GetFolderProperties_Completed(object sender, LiveOperationCompletedEventArgs e)
        {
            client.GetCompleted -= GetFolderProperties_Completed;
            if (e.Error == null)
            {
                Dictionary<string, object> folderData = (Dictionary<string, object>)e.Result;
                List<object> folders = (List<object>)folderData["data"];

                foreach (object item in folders)
                {
                    Dictionary<string, object> folder = (Dictionary<string, object>)item;
                    if (folder["name"].ToString() == skyDriveFolderName)
                        skyDriveFolderID = folder["id"].ToString();
                }

                if (skyDriveFolderID == string.Empty)
                {
                    Dictionary<string, object> skyDriveFolderData = new Dictionary<string, object>();
                    skyDriveFolderData.Add("name", skyDriveFolderName);

                    client.PostAsync("me/skydrive", skyDriveFolderData);
                }
                else
                    UploadFile();
            }
            else
            {
                SetBusy(false);
                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }

        //get backup folder
        private void client_BackupFolderGetCompleted(object sender, LiveOperationCompletedEventArgs e)
        {
            SetBusy(false);
            client.GetCompleted -= client_BackupFolderGetCompleted;
            if (e.Error == null)
            {
                Dictionary<string, object> folderData = (Dictionary<string, object>)e.Result;
                List<object> files = (List<object>)folderData["data"];

                List<Backup> backups = new List<Backup>();

                foreach (object file in files)
                {
                    Dictionary<string, object> f = (Dictionary<string, object>)file;

                    var backup = new Backup 
                    {
                         BackupFileUrl = f["id"].ToString(),
                         BackupTime = DateTime.Parse(f["created_time"].ToString()),
                         FileID = f["id"].ToString()
                    };

                    backups.Add(backup);
                }

                if (backups.Count > 0)
                {
                    viewmodel.MergeBackup(backups);
                }
                else 
                {
                    var toast = new ToastPrompt
                    {
                        Message = Resource.NoBackup,
                        FontSize = 22,
                        VerticalContentAlignment = System.Windows.VerticalAlignment.Top,
                        MillisecondsUntilHidden = 2000
                    };
                    toast.Show();
                }
            }
            else
            {
                
                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }

        }

        private void GetBackFolderProperties_Completed(object sender, LiveOperationCompletedEventArgs e)
        {
            client.GetCompleted -= GetBackFolderProperties_Completed;
            if (e.Error == null)
            {
                Dictionary<string, object> folderData = (Dictionary<string, object>)e.Result;
                List<object> folders = (List<object>)folderData["data"];

                foreach (object item in folders)
                {
                    Dictionary<string, object> folder = (Dictionary<string, object>)item;
                    if (folder["name"].ToString() == skyDriveFolderName)
                        skyDriveFolderID = folder["id"].ToString();
                }

                if (skyDriveFolderID == string.Empty)
                {
                    //Dictionary<string, object> skyDriveFolderData = new Dictionary<string, object>();
                    //skyDriveFolderData.Add("name", skyDriveFolderName);

                    //client.PostAsync("me/skydrive", skyDriveFolderData);
                    var toast = new ToastPrompt
                    {
                        Message = Resource.NoBackup,
                        FontSize = 22,
                        VerticalContentAlignment = System.Windows.VerticalAlignment.Top,
                        MillisecondsUntilHidden = 2000
                    };
                    toast.Show();
                    SetBusy(false);
                }
                else
                {
                    client.GetCompleted += client_BackupFolderGetCompleted;

                    client.GetAsync(skyDriveFolderID+"/files");
                }
            }
            else
            {
                SetBusy(false);
                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }

        }

        private void CreateFolder_Completed(object sender, LiveOperationCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                //infoTextBlock.Text = "Folder created.";
                Dictionary<string, object> folder = (Dictionary<string, object>)e.Result;
                skyDriveFolderID = folder["id"].ToString();
                UploadFile();
            }
            else
            {
                SetBusy(false);

                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }

        private void UploadFile()
        {
            if (!string.IsNullOrEmpty(skyDriveFolderID))
            {
                try
                {
                    stream = new MemoryStream();

                    var msgList = viewmodel.MsgDB.Messages.ToList();

                    var backup = new Backup
                    {
                        BackupTime = DateTime.UtcNow,
                        BackupFileUrl = Guid.NewGuid().ToString() + "_mc_" + count + ".TXT",
                        MessageCount = count
                    };

                    Serialize(stream, msgList);

                    stream.Position = 0;

                    client.UploadAsync(skyDriveFolderID, backup.BackupFileUrl, true, stream, backup);

                }
                catch (Exception e)
                {
                    SetBusy(false);
                    MessageBox.Show(e.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
                }
            }
        }

        private void ISFile_UploadCompleted(object sender, LiveOperationCompletedEventArgs args)
        {
            if (stream != null)
            {
                stream.Close();
                stream.Dispose();
            }

            SetBusy(false);

            if (args.Error == null)
            {
                try
                {
                    Dictionary<string, object> file = (Dictionary<string, object>)args.Result;
                    var fileid = file["id"].ToString();

                    var backup = args.UserState as Backup;
                    if (backup != null)
                    {
                        backup.FileID = fileid;
                        viewmodel.Insert(backup);

                        var toast = new ToastPrompt
                        {
                            Message = Resource.BackupCreated,
                            FontSize = 22,
                            VerticalContentAlignment = System.Windows.VerticalAlignment.Top,
                            MillisecondsUntilHidden = 2000
                        };
                        toast.Show();
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
                }
            }
            else
            {
                MessageBox.Show(args.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }

        void syncBackupButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(skyDriveFolderID))
            {
                client.GetCompleted += new EventHandler<LiveOperationCompletedEventArgs>(GetBackFolderProperties_Completed);
                // If you put photo to folder it becomes album. 
                client.GetAsync("me/skydrive/files?filter=folders");
            }
            else
            {
                client.GetCompleted+=new EventHandler<LiveOperationCompletedEventArgs>(client_BackupFolderGetCompleted);
                client.GetAsync(skyDriveFolderID+"/files");
            }

            SetBusy(true, Resource.Synchronizing);
        }

        void deleteBackupButton_Click(object sender, EventArgs e)
        {
            //throw new NotImplementedException();
            if (backupList.SelectedItems != null && backupList.SelectedItems.Count > 0)
            {
                var result = MessageBox.Show(Resource.ConfirmToDelete, "", MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.Cancel)
                    return;
                foreach (var item in backupList.SelectedItems)
                {
                    var backup = item as Backup;
                    if (backup != null)
                    {
                        client.DeleteAsync(backup.FileID, backup);
                        SetBusy(true,Resource.DeleteBackup);
                    }
                }
            }
            else
            {
                MessageBox.Show(Resource.SelectABackupRequired);
            }
        }

        public static void Serialize(Stream streamObject, object objForSerialization)
        {
            if (objForSerialization == null || streamObject == null)
                return;
            DataContractJsonSerializer ser = new DataContractJsonSerializer(objForSerialization.GetType());
            ser.WriteObject(streamObject, objForSerialization);
        }

        public static object Deserialize(Stream streamObject, Type serializedObjectType)
        {
            if (serializedObjectType == null || streamObject == null)
                return null;
            DataContractJsonSerializer ser = new DataContractJsonSerializer(serializedObjectType);
            return ser.ReadObject(streamObject);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var fe = sender as FrameworkElement;

            if (fe != null)
            {
                var backup = fe.DataContext as Backup;
                if (backup != null)
                {
                    if (session == null || status != LiveConnectSessionStatus.Connected)
                    {
                        MessageBox.Show(Resource.SigninRequired, "", MessageBoxButton.OK);
                    }
                    else
                    {
                        var result = MessageBox.Show(Resource.ConfirmToRestore, "", MessageBoxButton.OKCancel);
                        if (result == MessageBoxResult.Cancel)
                            return;

                        client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(client_DownloadCompleted);
                        client.DownloadAsync(backup.FileID + "/content", backup);
                        SetBusy(true,Resource.RestoreBackup);
                    }
                }
            }
        }
        
        void client_DownloadCompleted(object sender, LiveDownloadCompletedEventArgs e)
        {
            client.DownloadCompleted -= client_DownloadCompleted;
            SetBusy(false);
            if (e.Error == null)
            {
                var backup = e.UserState as Backup;
                if (backup != null)
                {
                    //infoTextBlock.Text = "Folder created.";
                    var messages = Deserialize(e.Result, typeof(List<Message>)) as List<Message>;
                    if (messages != null && messages.Count > 0)
                    {
                        viewmodel.Restore(messages);

                        var toast = new ToastPrompt
                        {
                            Message = string.Format(Resource.RestroedToBackup, backup.BackupTime),
                            FontSize = 22,
                            VerticalContentAlignment = System.Windows.VerticalAlignment.Top,
                            MillisecondsUntilHidden = 2000
                        };
                        toast.Show();
                    }
                }
            }
            else
            {
                MessageBox.Show(e.Error.Message, Resource.ErrorMessgeBoxTitle, MessageBoxButton.OK);
            }
        }
    }
}
